/*
* Copyright 2012-2017 CodeLibs Project and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.codelibs.fess.helper;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
import org.codelibs.fess.crawler.util.CharUtil;
import org.codelibs.fess.mylasta.action.FessMessages;
import org.codelibs.fess.mylasta.action.FessUserBean;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.util.ComponentUtil;
import org.codelibs.fess.validation.FessActionValidator;
import org.lastaflute.core.message.supplier.UserMessagesCreator;
import org.lastaflute.web.TypicalAction;
import org.lastaflute.web.ruts.process.ActionRuntime;
import org.lastaflute.web.servlet.request.RequestManager;
import org.lastaflute.web.validation.ActionValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.ibm.icu.util.ULocale;
public class SystemHelper {
private static final Logger logger = LoggerFactory.getLogger(SystemHelper.class);
protected final Map<String, String> designJspFileNameMap = new HashMap<>();
protected final AtomicBoolean forceStop = new AtomicBoolean(false);
protected LoadingCache<String, List<Map<String, String>>> langItemsCache;
protected String filterPathEncoding;
protected String[] supportedLanguages;
protected List<Runnable> shutdownHookList = new ArrayList<>();
protected Random random = new SecureRandom();
protected AtomicInteger previousClusterState = new AtomicInteger(0);
@PostConstruct
public void init() {
final FessConfig fessConfig = ComponentUtil.getFessConfig();
filterPathEncoding = fessConfig.getPathEncoding();
supportedLanguages = fessConfig.getSupportedLanguagesAsArray();
langItemsCache =
CacheBuilder.newBuilder().maximumSize(20).expireAfterAccess(1, TimeUnit.HOURS)
.build(new CacheLoader<String, List<Map<String, String>>>() {
@Override
public List<Map<String, String>> load(final String key) throws Exception {
final ULocale uLocale = new ULocale(key);
final Locale displayLocale = uLocale.toLocale();
final List<Map<String, String>> langItems = new ArrayList<>(supportedLanguages.length);
final String msg = ComponentUtil.getMessageManager().getMessage(displayLocale, "labels.allLanguages");
final Map<String, String> defaultMap = new HashMap<>(2);
defaultMap.put(Constants.ITEM_LABEL, msg);
defaultMap.put(Constants.ITEM_VALUE, "all");
langItems.add(defaultMap);
for (final String lang : supportedLanguages) {
final Locale locale = LocaleUtils.toLocale(lang);
final String label = locale.getDisplayName(displayLocale);
final Map<String, String> map = new HashMap<>(2);
map.put(Constants.ITEM_LABEL, label);
map.put(Constants.ITEM_VALUE, lang);
langItems.add(map);
}
return langItems;
}
});
ComponentUtil.doInitProcesses(p -> p.run());
}
@PreDestroy
public void destroy() {
shutdownHookList.forEach(action -> {
try {
action.run();
} catch (final Exception e) {
logger.warn("Failed to process shutdown task.", e);
}
});
}
public String getUsername() {
final RequestManager requestManager = ComponentUtil.getRequestManager();
return requestManager.findUserBean(FessUserBean.class).map(user -> {
return user.getUserId();
}).orElse(Constants.GUEST_USER);
}
public Date getCurrentTime() {
return new Date();
}
public long getCurrentTimeAsLong() {
return System.currentTimeMillis();
}
public LocalDateTime getCurrentTimeAsLocalDateTime() {
return LocalDateTime.now();
}
public String getLogFilePath() {
final String value = System.getProperty("fess.log.path");
if (value != null) {
return value;
} else {
final String userDir = System.getProperty("user.dir");
final File targetDir = new File(userDir, "target");
return new File(targetDir, "logs").getAbsolutePath();
}
}
public String encodeUrlFilter(final String path) {
if (filterPathEncoding == null || path == null) {
return path;
}
try {
final StringBuilder buf = new StringBuilder(path.length() + 100);
for (int i = 0; i < path.length(); i++) {
final char c = path.charAt(i);
if (CharUtil.isUrlChar(c) || c == '^' || c == '{' || c == '}' || c == '|' || c == '\\') {
buf.append(c);
} else {
buf.append(URLEncoder.encode(String.valueOf(c), filterPathEncoding));
}
}
return buf.toString();
} catch (final UnsupportedEncodingException e) {
return path;
}
}
public String getHelpLink(final String name) {
final String url = ComponentUtil.getFessConfig().getOnlineHelpBaseLink() + name + "-guide.html";
final Locale locale = ComponentUtil.getRequestManager().getUserLocale();
if (locale != null) {
final String lang = locale.getLanguage();
if (ComponentUtil.getFessConfig().isOnlineHelpSupportedLang(lang)) {
return url.replaceFirst("\\{lang\\}", lang).replaceFirst("\\{version\\}",
Constants.MAJOR_VERSION + "." + Constants.MINOR_VERSION);
}
}
return getDefaultHelpLink(url);
}
protected String getDefaultHelpLink(final String url) {
return url.replaceFirst("/\\{lang\\}/", "/").replaceFirst("\\{version\\}", Constants.MAJOR_VERSION + "." + Constants.MINOR_VERSION);
}
public void addDesignJspFileName(final String key, final String value) {
designJspFileNameMap.put(key, value);
}
public String getDesignJspFileName(final String fileName) {
return designJspFileNameMap.get(fileName);
}
public boolean isForceStop() {
return forceStop.get();
}
public void setForceStop(final boolean b) {
forceStop.set(true);
}
public String generateDocId(final Map<String, Object> map) {
return UUID.randomUUID().toString().replace("-", StringUtil.EMPTY);
}
public String abbreviateLongText(final String str) {
return StringUtils.abbreviate(str, ComponentUtil.getFessConfig().getMaxLogOutputLengthAsInteger().intValue());
}
public String normalizeLang(final String value) {
if (StringUtil.isBlank(value)) {
return null;
}
final String localeName = value.trim().toLowerCase(Locale.ENGLISH).replace("-", "_");
for (final String supportedLang : supportedLanguages) {
if (localeName.startsWith(supportedLang.toLowerCase(Locale.ENGLISH))) {
return supportedLang;
}
}
return null;
}
public List<Map<String, String>> getLanguageItems(final Locale locale) {
try {
final String localeStr = locale.toString();
return langItemsCache.get(localeStr);
} catch (final ExecutionException e) {
final List<Map<String, String>> langItems = new ArrayList<>(supportedLanguages.length);
final String msg = ComponentUtil.getMessageManager().getMessage(locale, "labels.allLanguages");
final Map<String, String> defaultMap = new HashMap<>(2);
defaultMap.put(Constants.ITEM_LABEL, msg);
defaultMap.put(Constants.ITEM_VALUE, "all");
langItems.add(defaultMap);
return langItems;
}
}
public void sleep(final int sec) {
try {
Thread.sleep(sec * 1000L);
} catch (final InterruptedException e) {
if (logger.isDebugEnabled()) {
logger.debug("Interrupted.", e);
}
}
}
public void addShutdownHook(final Runnable hook) {
shutdownHookList.add(hook);
}
public String getHostname() {
final Map<String, String> env = System.getenv();
if (env.containsKey("COMPUTERNAME")) {
return env.get("COMPUTERNAME");
} else if (env.containsKey("HOSTNAME")) {
return env.get("HOSTNAME");
}
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (final UnknownHostException e) {
logger.debug("Unknown hostname.", e);
}
return "Unknown";
}
public void setupAdminHtmlData(final TypicalAction action, final ActionRuntime runtime) {
// nothing
}
public String getSearchRoleByUser(final String name) {
return createSearchRole(ComponentUtil.getFessConfig().getRoleSearchUserPrefix(), name);
}
public String getSearchRoleByGroup(final String name) {
return createSearchRole(ComponentUtil.getFessConfig().getRoleSearchGroupPrefix(), name);
}
public String getSearchRoleByRole(final String name) {
return createSearchRole(ComponentUtil.getFessConfig().getRoleSearchRolePrefix(), name);
}
protected String createSearchRole(final String type, final String name) {
return type + name;
}
public void reloadConfiguration() {
ComponentUtil.getFessEsClient().refresh();
ComponentUtil.getLabelTypeHelper().init();
ComponentUtil.getPathMappingHelper().init();
ComponentUtil.getSuggestHelper().init();
ComponentUtil.getPopularWordHelper().init();
ComponentUtil.getJobManager().reboot();
ComponentUtil.getLdapManager().updateConfig();
}
public String generateAccessToken() {
return RandomStringUtils.random(ComponentUtil.getFessConfig().getApiAccessTokenLengthAsInteger().intValue(), 0, 0, true, true,
null, random);
}
public void setRandom(final Random random) {
this.random = random;
}
public boolean isChangedClusterState(final int status) {
return previousClusterState.getAndSet(status) != status;
}
public ActionValidator<FessMessages> createValidator(final RequestManager requestManager,
final UserMessagesCreator<FessMessages> messagesCreator, final Class<?>[] runtimeGroups) {
return new FessActionValidator<>(requestManager, messagesCreator, runtimeGroups);
}
}